package com.dragon.mmochat.service;

import java.awt.Color;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.dragon.mmochat.MmochatConstant;
import com.dragon.mmochat.MmochatMain;
import com.dragon.mmochat.message.Mmochat_6_6C;
import com.dragon.mmochat.message.Mmochat_6_7C;
import com.dragon.mmochat.model.enumType.MmochatFamilyType;
import com.dragon.mmochat.model.enumType.MmochatNpcItemType;
import com.dragon.mmochat.model.enumType.MmochatSkillType;
import com.dragon.mmochat.model.enumType.MmochatSmallMoneyCostType;
import com.dragon.mmochat.model.role.MmochatMonster;
import com.dragon.mmochat.model.role.MmochatPet;
import com.dragon.mmochat.model.role.MmochatPlayer;
import com.dragon.mmochat.model.role.MmochatRole;
import com.dragon.mmochat.model.skill.MmochatSkill;
import com.dragon.mmochat.model.skill.MmochatSkillData;
import com.dragon.mmochat.util.CreateTlvWin;
import com.dragon.mmochat.util.MmochatUtil;
import com.skymobi.handler.SkymobiHandler;
import com.skymobi.message.SkymobiProtocolMessage;
import com.skymobi.message.widget.AddDataTLV;
import com.skymobi.message.widget.ClearDataTLV;
import com.skymobi.message.widget.CloseWinTLV;
import com.skymobi.message.widget.SendDataTLV;
import com.skymobi.message.widget.ShowPopupMenuTLV;
import com.skymobi.message.widget.ShowWaitingMsgBoxTLV;
import com.skymobi.message.widget.WinType;
import com.skymobi.service.SkymobiService;
import com.skymobi.util.Text;

public class MmochatSkillService {
	private static Logger log = LoggerFactory
			.getLogger(MmochatSkillService.class);

	// 技能数值:Map<技能类型, Map<技能等级, 技能数值>>
	public static Map<MmochatSkillType, Map<Integer, MmochatSkillData>> skillData = new ConcurrentHashMap<MmochatSkillType, Map<Integer, MmochatSkillData>>();

	public MmochatSkillService() {
		if (!MmochatMain.openMergeServer) {
			// 加载技能数值
			log.debug("加载技能数值");
			loadSkillDataFromFolder("skill/attackSkill");
			loadSkillDataFromFolder("skill/limitSkill");
			loadSkillDataFromFolder("skill/assistSkill");
		}
	}

	// 加载文件夹下的所有数值文件
	public static void loadSkillDataFromFolder(String folder) {
		File root;
		File[] files;
		Pattern fileNamePattern = Pattern.compile("[^/]*\\.");
		root = new File(folder);
		files = root.listFiles();
		if (files != null) {
			for (File file : files) {
				if (!file.isFile()) {
					continue;
				}
				String fileName = file.getName();
				Matcher matcher = fileNamePattern.matcher(fileName);
				if (matcher.find()) {
					String fileStr = matcher.group();
					fileStr = fileStr.substring(0, fileStr.length() - 1);
					log.debug("技能名:" + fileStr);
					MmochatSkillType skillType = MmochatSkillType
							.getSkillByShortName(fileStr);
					if (skillType == null) {
						throw new RuntimeException(folder + "," + fileStr
								+ "：没有对应的技能");
					}
					skillData.put(skillType, parseSkillDataFromFile(file,
							skillType));
				}
			}
		}
	}

	// 解析一个技能数值文件
	private static Map<Integer, MmochatSkillData> parseSkillDataFromFile(
			File file, MmochatSkillType skillType) {
		Map<Integer, MmochatSkillData> map = new ConcurrentHashMap<Integer, MmochatSkillData>();
		if (file.exists()) {
			if (file.isFile()) {
				try {
					BufferedReader reader = new BufferedReader(new FileReader(
							file));
					String lineBuf;
					int maxSkillLevel = 0;
					while ((lineBuf = reader.readLine()) != null) {
						if (lineBuf.trim() == "") {
							continue;
						}
						String[] array = lineBuf.split("\t");
						if (array != null && array.length > 0) {
							if (array.length != 7) {
								throw new RuntimeException(file.getName()
										+ "中的技能数值项，不是7项");
							}
							double[] values = new double[array.length];
							for (int i = 0; i < array.length; i++) {
								try {
									values[i] = Double.parseDouble(array[i]);
								} catch (NumberFormatException e) {
									e.printStackTrace();
									throw new RuntimeException(file.getName()
											+ "中有非数字!");
								}
							}
							MmochatSkillData data = new MmochatSkillData();
							data.setSkillLevel((int) values[0]);// 技能等级
							data.setEffectValue(values[1]);// 技能效果值
							data.setTargetNum((int) values[2]);// 技能目标数
							data.setKeepRound((int) values[3]);// 持续回合数
							data.setCostSprit((int) values[4]);// 消耗法力
							data.setLevelNeedToLearn((int) values[5]);// 技能学习等级要求
							data.setDaoNeedToLearn((int) values[6]);// 技能学习道行要求
							map.put(data.getSkillLevel(), data);
							maxSkillLevel = (int) Math.max(maxSkillLevel,
									values[0]);
						}
					}
					skillType.setMaxLevel(maxSkillLevel);
				} catch (FileNotFoundException e) {
					e.printStackTrace();
					throw new RuntimeException("文件缺失!文件名:" + file.getName());
				} catch (IOException e) {
					e.printStackTrace();
					throw new RuntimeException("读取出错!文件名:" + file.getName());
				}
			} else {
				throw new RuntimeException("文件缺失!文件名:" + file.getName());
			}
		} else {
			throw new RuntimeException("文件缺失!文件名:" + file.getName());
		}
		return map;
	}

	// 获得技能效果值
	public static double getEffectValue(MmochatSkillType type, int level) {
		double value = 0;
		if (level == 0) {
			return 0;
		}
		try {
			MmochatSkillData skillData = MmochatSkillService.skillData
					.get(type).get(level);
			value = skillData.getEffectValue();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return value;
	}

	// 获得目标数
	public static int getTargetNum(MmochatRole role, MmochatSkillType type,
			int level) {
		int value = 0;
		if (role instanceof MmochatMonster) {
			// 宠物、怪等的攻击目标由技能类型决定
			return type.getMaxTargetNum();
		}
		if (level == 0) {
			return 0;
		}
		try {
			MmochatSkillData skillData = MmochatSkillService.skillData
					.get(type).get(level);
			value = skillData.getTargetNum();
		} catch (Exception e) {
			e.printStackTrace();
		}

		return value;
	}

	// 获得持续回合数
	public static int getKeepRound(MmochatSkillType type, int level) {
		int value = 0;
		if (level == 0) {
			return 0;
		}
		try {
			MmochatSkillData skillData = MmochatSkillService.skillData
					.get(type).get(level);
			value = skillData.getKeepRound();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return value;
	}

	// 获得消耗法力
	public static int getCostSprit(MmochatSkillType type, int level,
			boolean isPet) {
		int value = 0;
		if (isPet) {
			// 宠物的技能等级
			level = type.getMaxLevel();
			if (level == 0) {
				return 0;
			}
			try {
				MmochatSkillData skillData = MmochatSkillService.skillData.get(
						type).get(level);
				value = (int) (skillData.getCostSprit() * 0.6);
			} catch (Exception e) {
				e.printStackTrace();
			}
		} else {
			if (level == 0) {
				return 0;
			}
			try {
				MmochatSkillData skillData = MmochatSkillService.skillData.get(
						type).get(level);
				value = skillData.getCostSprit();
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		return value;
	}

	// 学习技能的人物等级要求
	public static int getLevelNeedToLearn(MmochatSkillType type, int level) {
		int value = 0;
		if (level == 0) {
			return 0;
		}
		level = Math.min(level, type.getMaxLevel());
		try {
			MmochatSkillData skillData = MmochatSkillService.skillData
					.get(type).get(level);
			value = skillData.getLevelNeedToLearn();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return value;
	}

	// 学习技能的人物道行要求(天)
	public static int getDaoNeedToLearn(MmochatSkillType type, int level) {
		int value = 0;
		if (level == 0) {
			return 0;
		}
		level = Math.min(level, type.getMaxLevel());
		try {
			MmochatSkillData skillData = MmochatSkillService.skillData
					.get(type).get(level);
			value = skillData.getDaoNeedToLearn();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return value;
	}

	public static CreateTlvWin getSkillInfoWin(MmochatPlayer me,
			MmochatSkillType skillType) {
		if (me == null) {
			return null;
		}
		if (skillType == null) {
			return null;
		}
		int mySkillLevel = me.getSkillLevel(skillType);
		int moneyNeed;

		CreateTlvWin tlv = new CreateTlvWin();
		tlv.setWinType(WinType.Text);
		tlv.setLeftName("菜单");
		tlv.setRightName("返回");
		tlv.setTitle(skillType.toString());
		tlv.setWinHeight(188);
		tlv.setWinId(MmochatConstant.TLV_WIN_SKILL_INFO);
		tlv.addRightTLV(new CloseWinTLV(MmochatConstant.TLV_WIN_SKILL_INFO));
		String content = "";
		content += "技能名：" + skillType.toString() + "\n";
		content += "技能等级：" + mySkillLevel + "/" + skillType.getMaxLevel()
				+ "\n";
		content += "当前目标数：" + getTargetNum(me, skillType, mySkillLevel) + "\n";
		content = MmochatUtil.wrapColor(content, Color.yellow);
		String content2 = "";
		content2 += "\n下级技能学习要求:\n";
		int nextLevelNeed = getLevelNeedToLearn(skillType, mySkillLevel + 1);
		int turn = 0;
		int showNextLevel = nextLevelNeed;
		if (nextLevelNeed > MmochatConstant.maxLevel) {
			turn = (nextLevelNeed - MmochatConstant.maxLevel + 9) / 10;
			showNextLevel = nextLevelNeed - turn * 10;
		}
		if (turn > 0) {
			content2 += "人物等级:" + turn + "转" + showNextLevel + "级\n";
		} else {
			content2 += "人物等级:" + nextLevelNeed + "级\n";
		}
		content2 += "人物道行:"
				+ MmochatUtil.getDaoString(getDaoNeedToLearn(skillType,
						mySkillLevel + 1)) + "\n";
		// 金钱要求=技能等级*目标数*10
		int nextSkillLevel = Math
				.min(mySkillLevel + 1, skillType.getMaxLevel());
		int targetNum = getTargetNum(me, skillType, nextSkillLevel);
		moneyNeed = nextSkillLevel * targetNum * 10;
		if (nextLevelNeed <= 30) {
			moneyNeed = 0;
		}
		content2 += "消耗金钱：" + moneyNeed + "文\n";
		content2 = MmochatUtil.wrapColor(content2, Color.green);

		content = content + content2 + "\n" + skillType.getInfo();
		tlv.setContent(new Text(content));

		// 菜单
		ShowWaitingMsgBoxTLV wait = new ShowWaitingMsgBoxTLV();
		wait.setShowCancel(false);

		ShowPopupMenuTLV menu = new ShowPopupMenuTLV();
		menu.addItemEvent("学习一级", new ClearDataTLV(), new AddDataTLV(
				(int) skillType.getKey()),
				new AddDataTLV((int) me.getRoleId()), new SendDataTLV(
						MmochatConstant.getClientModuleId(), MmochatMain
								.getModuleInstID(),
						MmochatConstant.MSGCODE_MMOCHAT_C_6_7, (int) 1), wait);

		menu.addItemEvent("尽可能多的学", new ClearDataTLV(), new AddDataTLV(
				(int) skillType.getKey()),
				new AddDataTLV((int) me.getRoleId()), new SendDataTLV(
						MmochatConstant.getClientModuleId(), MmochatMain
								.getModuleInstID(),
						MmochatConstant.MSGCODE_MMOCHAT_C_6_7, (int) 1000),
				wait);

		tlv.addLeftTLV(menu);

		return tlv;
	}

	// 6.6 查看技能
	@SkymobiService
	public SkymobiProtocolMessage handleC_6_6(SkymobiHandler handler,
			Mmochat_6_6C req) {
		MmochatPlayer me = MmochatMainService.getPlayerByRoleId(req, req
				.getRoleId());
		if (me == null) {
			return MmochatUtil.msgbox(req.getHallState(), "服务器忙,请稍候再试!");
		}
		MmochatSkillType skillType = MmochatSkillType.get(req.getSkillKey());
		if (skillType == null) {
			return MmochatUtil.msgbox(req.getHallState(), "没有此项技能!");
		}

		CreateTlvWin tlv = getSkillInfoWin(me, skillType);
		return MmochatUtil.tlvResponse(req.getHallState(), new CloseWinTLV(
				MmochatConstant.TLV_WIN_SKILL_INFO), tlv);
	}

	// 6.7 学习技能
	@SkymobiService
	public SkymobiProtocolMessage handleC_6_7(SkymobiHandler handler,
			Mmochat_6_7C req) {
		MmochatPlayer me = MmochatMainService.getPlayerByRoleId(req, req
				.getRoleId());
		if (me == null) {
			return MmochatUtil.msgbox(req.getHallState(), "服务器忙,请稍候再试!");
		}
		MmochatSkillType skillType = MmochatSkillType.get(req.getSkillKey());
		if (skillType == null) {
			return MmochatUtil.msgbox(req.getHallState(), "没有此项技能!");
		}

		// 技能门派检查
		if (skillType.getSkillFamily() != me.getFamily()) {
			return MmochatUtil.msgbox(req.getHallState(), "你非本派弟子，不能学习本派技能!");
		}
		// 前置技能要求
		MmochatSkillType preSkillType = MmochatSkillType.getPreSkill(skillType);
		if (preSkillType != null) {
			int myPreSkillLevel = me.getSkillLevel(preSkillType);
			if (myPreSkillLevel < preSkillType.getMaxLevel()) {
				return MmochatUtil.msgbox(req.getHallState(), "学习应循序渐进!你的"
						+ preSkillType.toString() + "技能尚未完全掌握，无法学习此技能!");
			}
		}

		int mySkillLevel;
		int moneyNeed;
		MmochatSkill mySkill;
		int levelCount = req.getLevelCount();
		synchronized (me) {
			// 技能是否已学满
			mySkillLevel = me.getSkillLevel(skillType);
			if (mySkillLevel >= skillType.getMaxLevel()) {
				return MmochatUtil.msgbox(req.getHallState(), "此技能已学满!");
			}
			if (levelCount <= 1) {
				// 下级等级要求
				int levelNeed = getLevelNeedToLearn(skillType, mySkillLevel + 1);
				if (me.getTrueLevel() < levelNeed) {
					return MmochatUtil.msgbox(req.getHallState(),
							"等级不够，无法继续学习此技能!");
				}
				// 下级道行要求
				int daoNeed = getDaoNeedToLearn(skillType, mySkillLevel + 1);
				if (me.getDao() < daoNeed) {
					return MmochatUtil.msgbox(req.getHallState(),
							"道行不够，无法继续学习此技能!");
				}
				// 金钱要求=技能等级*目标数*10
				int nextSkillLevel = Math.min(mySkillLevel + 1, skillType
						.getMaxLevel());
				int targetNum = getTargetNum(me, skillType, nextSkillLevel);
				moneyNeed = nextSkillLevel * targetNum * 10;
				if (levelNeed <= 30) {
					moneyNeed = 0;
				}
				if (me.getSmall_money() < moneyNeed) {
					return MmochatUtil.msgbox(req.getHallState(), "学习此技能需要"
							+ MmochatUtil.getColorMoney(moneyNeed)
							+ "文钱，你包裹中的金钱不足。");
				}
				mySkill = me.getSkill(skillType);
				if (mySkill == null) {
					mySkill = new MmochatSkill();
					mySkill.setLevel(mySkillLevel);
					mySkill.setType(skillType);
					me.addNewSkill(mySkill);
				}
				mySkill.setLevel(mySkillLevel + 1);
				me.addAndUpdateSmall_money(-1 * moneyNeed);

				try {
					MmochatDao.updateRoleSkills(me, moneyNeed);
				} catch (Exception e) {
					mySkill.setLevel(mySkillLevel);
					me.addSmall_money(moneyNeed);
					e.printStackTrace();
					return MmochatUtil
							.msgbox(req.getHallState(), "服务器忙,请稍候再试!");
				}

				MmochatStatisticsService.addSmallMoneyCost(
						MmochatSmallMoneyCostType.学习技能, -1 * moneyNeed);
			} else {
				int totalMoneyNeed = 0;
				int oldSkillLevel = me.getSkillLevel(skillType);
				for (int i = 0; i < levelCount; i++) {
					// 技能是否已学满
					mySkillLevel = me.getSkillLevel(skillType);
					if (mySkillLevel >= skillType.getMaxLevel()) {
						// 此技能已学满!
						break;
					}
					// 下级等级要求
					int levelNeed = getLevelNeedToLearn(skillType,
							mySkillLevel + 1);
					if (me.getTrueLevel() < levelNeed) {
						// 等级不够，无法继续学习此技能!
						break;
					}
					// 下级道行要求
					int daoNeed = getDaoNeedToLearn(skillType, mySkillLevel + 1);
					if (me.getDao() < daoNeed) {
						// 道行不够，无法继续学习此技能!
						break;
					}
					// 金钱要求=技能等级*目标数*10
					int nextSkillLevel = Math.min(mySkillLevel + 1, skillType
							.getMaxLevel());
					int targetNum = getTargetNum(me, skillType, nextSkillLevel);
					moneyNeed = nextSkillLevel * targetNum * 10;
					if (levelNeed <= 30) {
						moneyNeed = 0;
					}
					if (me.getSmall_money() < totalMoneyNeed + moneyNeed) {
						// 金钱不足
						break;
					}
					totalMoneyNeed += moneyNeed;
					mySkill = me.getSkill(skillType);
					if (mySkill == null) {
						mySkill = new MmochatSkill();
						mySkill.setLevel(mySkillLevel);
						mySkill.setType(skillType);
						me.addNewSkill(mySkill);
					}
					mySkill.setLevel(mySkillLevel + 1);
				}
				totalMoneyNeed = Math.max(0, totalMoneyNeed);
				me.addAndUpdateSmall_money(-1 * totalMoneyNeed);

				try {
					MmochatDao.updateRoleSkills(me, totalMoneyNeed);
				} catch (Exception e) {
					mySkill = me.getSkill(skillType);
					if (mySkill != null) {
						mySkill.setLevel(oldSkillLevel);
					}
					me.addAndUpdateSmall_money(totalMoneyNeed);
					e.printStackTrace();
					return MmochatUtil
							.msgbox(req.getHallState(), "服务器忙,请稍候再试!");
				}

				MmochatStatisticsService.addSmallMoneyCost(
						MmochatSmallMoneyCostType.学习技能, -1 * totalMoneyNeed);
			}
		}

		// 更新技能列表信息
		String title = "";
		switch (skillType.getSkillType()) {
		case MmochatSkill.攻击技能:
			title = "法术技能";
			break;
		case MmochatSkill.障碍技能:
			title = "障碍技能";
			break;
		case MmochatSkill.辅助技能:
			title = "辅助技能";
			break;
		default:
			break;
		}
		MmochatFamilyType family = me.getFamily();
		List<MmochatSkillType> skills = new ArrayList<MmochatSkillType>();
		for (MmochatSkillType type1 : MmochatSkillType.values()) {
			if (type1.getSkillFamily() == family
					&& type1.getSkillType() == skillType.getSkillType()) {
				skills.add(type1);
			}
		}
		CreateTlvWin tlv = new CreateTlvWin();
		tlv.setWinType(WinType.List);
		tlv.setLeftName("查看");
		tlv.setRightName("返回");
		tlv.setTitle(title);
		tlv.setWinHeight(188);
		tlv.setWinId(MmochatConstant.TLV_WIN_SKILL_LIST);
		tlv.addRightTLV(new CloseWinTLV(MmochatConstant.TLV_WIN_SKILL_LIST));

		for (MmochatSkillType skill : skills) {
			String item = skill.toString();
			int myLevel = me.getSkillLevel(skill);
			int maxLevel = skill.getMaxLevel();
			item += "(" + myLevel + "/" + maxLevel + ")";
			tlv.addItemEvent(item, new ClearDataTLV(), new AddDataTLV(
					(int) skill.getKey()));
		}
		tlv.addLeftTLV(new SendDataTLV(MmochatConstant.getClientModuleId(),
				MmochatMain.getModuleInstID(),
				MmochatConstant.MSGCODE_MMOCHAT_C_6_6, (int) me.getRoleId()));
		ShowWaitingMsgBoxTLV wait = new ShowWaitingMsgBoxTLV();
		tlv.addLeftTLV(wait);

		// 更新技能介绍面板
		CreateTlvWin tlv2 = getSkillInfoWin(me, skillType);
		return MmochatUtil.tlvResponse(req.getHallState(), new CloseWinTLV(
				MmochatConstant.TLV_WIN_SKILL_INFO), new CloseWinTLV(
				MmochatConstant.TLV_WIN_SKILL_LIST), tlv, tlv2);
	}
}
